﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Cqrs.Infrastructure;
using System.Threading;

namespace Meditime.UI
{
    public partial class ShiftTimeEditor : Form
    {
        private Guid _selectedGuid = Guid.Empty;
        private int _selectedRow = 0;

        public ShiftTimeEditor()
        {
            InitializeComponent();
        }

        private void llbAddShiftTime_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {

            AddShiftTime addShift = new AddShiftTime();

            try
            {
                Guid staffMemberId;
                Action commandAction;

                if (dgCurrentStatus.SelectedRows.Count > 0)
                {
                    var selectedShift = dgCurrentStatus.SelectedRows[0].DataBoundItem as CurrentShiftStatus;
                    staffMemberId = selectedShift.StaffMemberId;
                    commandAction = addShift.AddShift(staffMemberId);
                }
                else
                {
                    commandAction = addShift.AddShift();
                }

                if (commandAction != null)
                {
                    SubmitCommand(commandAction);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(Common.FormatError(ex));
            }
            finally
            {
                addShift = null;
            }
        }

        private void RefreshMembersGrid()
        {
            dgCurrentStatus.Columns.Clear();
            dgCurrentStatus.Columns.Add("Status", "Loading...");
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += (s, e) =>
            {
                try
                {
                    e.Result = GetCurrentStatuses();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(Common.FormatError(ex));
                }
            };
            worker.RunWorkerCompleted += PopulateMemberGrid;
            worker.RunWorkerAsync();
        }

        private void RefreshTimesGridForSelectedMember()
        {
            if (_selectedGuid == Guid.Empty) return;
            dgShiftTimes.Columns.Clear();
            dgShiftTimes.Columns.Add("Status", "Loading...");
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += (s, e) =>
            {
                try
                {
                    e.Result = GetAllTimesForStaffMember(_selectedGuid);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(Common.FormatError(ex));
                }
            };
            worker.RunWorkerCompleted += PopulateTimesGrid;
            worker.RunWorkerAsync();
        }

        private List<ShiftTime> GetAllTimesForStaffMember(Guid staffMemberId)
        {
            using (ReadModelEntities readmodel = new ReadModelEntities())
            {
                return (from time in readmodel.ShiftTimes
                        where time.MemberId == staffMemberId
                        orderby time.TimeStarted
                        select time).ToList();
            }
        }

        private List<CurrentShiftStatus> GetCurrentStatuses()
        {
            using (ReadModelEntities readmodelDb = new ReadModelEntities())
            {
                return (from status in readmodelDb.CurrentShiftStatuses
                        select status).ToList();
            }
        }

        private void SubmitCommand(Action commandAction)
        {
            dgShiftTimes.Columns.Clear();
            dgShiftTimes.DataSource = null;
            dgShiftTimes.Columns.Add("Status", "Waiting for Command...");
            dgShiftTimes.Columns[0].Width = Convert.ToInt32(dgCurrentStatus.Width * 0.9);
            btnRefresh.Enabled = false;
            ThreadPool.QueueUserWorkItem(p =>
            {
                try
                {
                    commandAction();
                    CommandNotifier.Instance.WriteToTextBox("The Shift Time change completed successfully.");
                }
                catch (Exception ex)
                {
                    CommandNotifier.Instance.WriteToTextBox(Common.FormatError(ex), true);
                }
                finally
                {
                    PopulateTimesGrid(this, new RunWorkerCompletedEventArgs(GetAllTimesForStaffMember(_selectedGuid), null, false));
                }
            });
            CommandNotifier.Instance.WriteToTextBox("The Shift Time change has been submitted.");
        }

        delegate void PopulateMemberGridMethod(object sender, RunWorkerCompletedEventArgs e);
        void PopulateMemberGrid(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                if (dgCurrentStatus.InvokeRequired)
                {
                    dgCurrentStatus.Invoke(new PopulateMemberGridMethod(PopulateMemberGrid), new object[] { sender, e });
                    return;
                }
                dgCurrentStatus.DataSource = GetCurrentStatuses();
                dgCurrentStatus.Columns[0].Visible = false;
                if (dgCurrentStatus.Rows.Count > 0) 
                    dgCurrentStatus.Rows[_selectedRow].Selected = true;
                btnRefresh.Enabled = true;
            }
            catch (Exception ex)
            {
                CommandNotifier.Instance.WriteToTextBox(Common.FormatError(ex), true);
            }
        }

        delegate void PopulateTimesGridMethod(object sender, RunWorkerCompletedEventArgs e);
        private void PopulateTimesGrid(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                if (dgShiftTimes.InvokeRequired)
                {
                    dgShiftTimes.Invoke(new PopulateTimesGridMethod(PopulateTimesGrid), new object[] { sender, e });
                    return;
                }
                dgShiftTimes.DataSource = e.Result;
                dgShiftTimes.Columns[0].Visible = false;
                btnRefresh.Enabled = true;
            }
            catch (Exception ex)
            {
                CommandNotifier.Instance.WriteToTextBox(Common.FormatError(ex), true);
            }
        }

        private void dgCurrentStatus_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                var selectedShift = dgCurrentStatus.SelectedRows[0].DataBoundItem as CurrentShiftStatus;
                _selectedGuid = selectedShift.StaffMemberId;
                _selectedRow = dgCurrentStatus.SelectedRows[0].Index;
                RefreshTimesGridForSelectedMember();
            }
            catch (Exception ex)
            {
                MessageBox.Show(Common.FormatError(ex));
            }
        }

        private void ShiftTimeEditor_Load(object sender, EventArgs e)
        {
            try
            {
                this.Top = 0;
                this.Left = 0;
                this.Width = this.Parent.Width - (CommandNotifier.Instance.Width + 6);
                this.Height = this.Parent.Height - 4;
                RefreshMembersGrid();
                RefreshTimesGridForSelectedMember();
            }
            catch (Exception ex)
            {
                MessageBox.Show(Common.FormatError(ex));
            }
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            try
            {
                RefreshMembersGrid();
                RefreshTimesGridForSelectedMember();
            }
            catch (Exception ex)
            {
                MessageBox.Show(Common.FormatError(ex));
            }
        }


    }
}
